<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  
  <style>

  .node circle {
    cursor: pointer;
    fill: #fff;
    stroke: steelblue;
    stroke-width: 2px;
  }

  .node text {
    font-size: 12px;
  }

  .link {
    fill: none;
    stroke: #ccc;
    stroke-width: 1.5px;
  }

  </style>
  </head> 
<body>
<script src="./files/d3.min.js"></script>
<script>

var width = 600;
var height = 500;

//边界空白
var padding = {left: 80, right:50, top: 20, bottom: 20 };

var svg = d3.select("body")
           .append("svg")
	         .attr("width", width + padding.left + padding.right)
	         .attr("height", height + padding.top + padding.bottom)
           .append("g")
           .attr("transform","translate("+ padding.left + "," + padding.top + ")");

//树状图布局
var tree = d3.layout.tree()
            .size([height, width]);

//对角线生成器
var diagonal = d3.svg.diagonal()
    .projection(function(d) { return [d.y, d.x]; });


d3.json("learn.json",function(error,root){

  //给第一个节点添加初始坐标x0和x1
  root.x0 = height / 2;
  root.y0 = 0;

  //以第一个节点为起始节点，重绘
  redraw(root);

  //重绘函数
  function redraw(source){

    /*
    （1） 计算节点和连线的位置
    */

    //应用布局，计算节点和连线
    var nodes = tree.nodes(root);
    var links = tree.links(nodes);

    //重新计算节点的y坐标
    nodes.forEach(function(d) { d.y = d.depth * 180; });

    /*
    （2） 节点的处理
    */

    //获取节点的update部分
    var nodeUpdate = svg.selectAll(".node")
                        .data(nodes, function(d){ return d.name; });

    //获取节点的enter部分
    var nodeEnter = nodeUpdate.enter();

    //获取节点的exit部分
    var nodeExit = nodeUpdate.exit();

    //1. 节点的 Enter 部分的处理办法
    var enterNodes = nodeEnter.append("g")
                    .attr("class","node")
                    .attr("transform", function(d) { return "translate(" + source.y0 + "," + source.x0 + ")"; })
                    .on("click", function(d) { toggle(d); redraw(d); });

    enterNodes.append("circle")
      .attr("r", 0)
      .style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; });

    enterNodes.append("text")
        .attr("x", function(d) { return d.children || d._children ? -14 : 14; })
        .attr("dy", ".35em")
        .attr("text-anchor", function(d) { return d.children || d._children ? "end" : "start"; })
        .text(function(d) { return d.name; })
        .style("fill-opacity", 0);


    //2. 节点的 Update 部分的处理办法
    var updateNodes = nodeUpdate.transition()
                        .duration(500)
                        .attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; });

    updateNodes.select("circle")
      .attr("r", 8)
      .style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; });

    updateNodes.select("text")
      .style("fill-opacity", 1);

    //3. 节点的 Exit 部分的处理办法
    var exitNodes = nodeExit.transition()
                      .duration(500)
                      .attr("transform", function(d) { return "translate(" + source.y + "," + source.x + ")"; })
                      .remove();

    exitNodes.select("circle")
      .attr("r", 0);

    exitNodes.select("text")
      .style("fill-opacity", 0);

    /*
    （3） 连线的处理
    */

    //获取连线的update部分
    var linkUpdate = svg.selectAll(".link")
                        .data(links, function(d){ return d.target.name; });

    //获取连线的enter部分
    var linkEnter = linkUpdate.enter();

    //获取连线的exit部分
    var linkExit = linkUpdate.exit();

    //1. 连线的 Enter 部分的处理办法
    linkEnter.insert("path",".node")
          .attr("class", "link")
          .attr("d", function(d) {
              var o = {x: source.x0, y: source.y0};
              return diagonal({source: o, target: o});
          })
          .transition()
          .duration(500)
          .attr("d", diagonal);

    //2. 连线的 Update 部分的处理办法
    linkUpdate.transition()
        .duration(500)
        .attr("d", diagonal);

    //3. 连线的 Exit 部分的处理办法
    linkExit.transition()
          .duration(500)
          .attr("d", function(d) {
            var o = {x: source.x, y: source.y};
            return diagonal({source: o, target: o});
          })
          .remove();


    /*
    （4） 将当前的节点坐标保存在变量x0、y0里，以备更新时使用
    */
    nodes.forEach(function(d) {
      d.x0 = d.x;
      d.y0 = d.y;
    });

  }

  //切换开关，d 为被点击的节点
  function toggle(d){
    if(d.children){ //如果有子节点
      d._children = d.children; //将该子节点保存到 _children
      d.children = null;  //将子节点设置为null
    }else{  //如果没有子节点
      d.children = d._children; //从 _children 取回原来的子节点 
      d._children = null; //将 _children 设置为 null
    }
  }

});

</script>
<!--<svg width="730" height="540">
	<g transform="translate(80,20)">
		<path class="link" d="M0,259.6153846153846C90,259.6153846153846 90,48.07692307692307 180,48.07692307692307">
			
		</path>
		<path class="link" d="M0,259.6153846153846C90,259.6153846153846 90,158.65384615384616 180,158.65384615384616">
			
		</path><path class="link" d="M0,259.6153846153846C90,259.6153846153846 90,331.7307692307692 180,331.7307692307692"></path><path class="link" d="M0,259.6153846153846C90,259.6153846153846 90,471.15384615384613 180,471.15384615384613"></path><path class="link" d="M180,48.07692307692307C270,48.07692307692307 270,19.23076923076923 360,19.23076923076923"></path><path class="link" d="M180,48.07692307692307C270,48.07692307692307 270,38.46153846153846 360,38.46153846153846"></path><path class="link" d="M180,48.07692307692307C270,48.07692307692307 270,57.69230769230769 360,57.69230769230769"></path><path class="link" d="M180,48.07692307692307C270,48.07692307692307 270,76.92307692307692 360,76.92307692307692"></path><path class="link" d="M180,158.65384615384616C270,158.65384615384616 270,115.38461538461539 360,115.38461538461539"></path><path class="link" d="M180,158.65384615384616C270,158.65384615384616 270,182.69230769230768 360,182.69230769230768"></path><path class="link" d="M180,158.65384615384616C270,158.65384615384616 270,201.9230769230769 360,201.9230769230769"></path><path class="link" d="M360,115.38461538461539C450,115.38461538461539 450,96.15384615384615 540,96.15384615384615"></path><path class="link" d="M360,115.38461538461539C450,115.38461538461539 450,115.38461538461539 540,115.38461538461539"></path><path class="link" d="M360,115.38461538461539C450,115.38461538461539 450,134.6153846153846 540,134.6153846153846"></path><path class="link" d="M360,182.69230769230768C450,182.69230769230768 450,173.07692307692307 540,173.07692307692307"></path><path class="link" d="M360,182.69230769230768C450,182.69230769230768 450,192.3076923076923 540,192.3076923076923"></path><path class="link" d="M180,331.7307692307692C270,331.7307692307692 270,240.3846153846154 360,240.3846153846154"></path><path class="link" d="M180,331.7307692307692C270,331.7307692307692 270,298.07692307692304 360,298.07692307692304"></path><path class="link" d="M180,331.7307692307692C270,331.7307692307692 270,331.7307692307692 360,331.7307692307692"></path><path class="link" d="M180,331.7307692307692C270,331.7307692307692 270,365.38461538461536 360,365.38461538461536"></path><path class="link" d="M180,331.7307692307692C270,331.7307692307692 270,384.6153846153846 360,384.6153846153846"></path><path class="link" d="M180,331.7307692307692C270,331.7307692307692 270,403.8461538461538 360,403.8461538461538"></path><path class="link" d="M180,331.7307692307692C270,331.7307692307692 270,423.07692307692304 360,423.07692307692304"></path><path class="link" d="M360,240.3846153846154C450,240.3846153846154 450,230.76923076923077 540,230.76923076923077"></path><path class="link" d="M360,240.3846153846154C450,240.3846153846154 450,250 540,250"></path><path class="link" d="M360,298.07692307692304C450,298.07692307692304 450,288.46153846153845 540,288.46153846153845"></path><path class="link" d="M360,298.07692307692304C450,298.07692307692304 450,307.6923076923077 540,307.6923076923077"></path><path class="link" d="M360,365.38461538461536C450,365.38461538461536 450,346.15384615384613 540,346.15384615384613"></path><path class="link" d="M360,365.38461538461536C450,365.38461538461536 450,365.38461538461536 540,365.38461538461536"></path><path class="link" d="M360,365.38461538461536C450,365.38461538461536 450,384.6153846153846 540,384.6153846153846"></path><path class="link" d="M180,471.15384615384613C270,471.15384615384613 270,461.53846153846155 360,461.53846153846155"></path><path class="link" d="M180,471.15384615384613C270,471.15384615384613 270,480.7692307692308 360,480.7692307692308"></path><path class="link" d="M360,461.53846153846155C450,461.53846153846155 450,442.30769230769226 540,442.30769230769226"></path><path class="link" d="M360,461.53846153846155C450,461.53846153846155 450,461.53846153846155 540,461.53846153846155"></path><path class="link" d="M360,461.53846153846155C450,461.53846153846155 450,480.7692307692308 540,480.7692307692308"></path><g class="node" transform="translate(0,259.6153869628906)"><circle r="8" style="fill: rgb(255, 255, 255);"></circle><text x="-14" dy=".35em" text-anchor="end" style="fill-opacity: 1;">如何学习D3</text></g><g class="node" transform="translate(180,48.07692337036133)"><circle r="8" style="fill: rgb(255, 255, 255);"></circle><text x="-14" dy=".35em" text-anchor="end" style="fill-opacity: 1;">预备知识</text></g><g class="node" transform="translate(360,19.230770111083984)"><circle r="8" style="fill: rgb(255, 255, 255);"></circle><text x="14" dy=".35em" text-anchor="start" style="fill-opacity: 1;">HTML &amp; CSS</text></g><g class="node" transform="translate(360,38.46154022216797)"><circle r="8" style="fill: rgb(255, 255, 255);"></circle><text x="14" dy=".35em" text-anchor="start" style="fill-opacity: 1;">JavaScript</text></g><g class="node" transform="translate(360,57.69230651855469)"><circle r="8" style="fill: rgb(255, 255, 255);"></circle><text x="14" dy=".35em" text-anchor="start" style="fill-opacity: 1;">DOM</text></g><g class="node" transform="translate(360,76.92308044433594)"><circle r="8" style="fill: rgb(255, 255, 255);"></circle><text x="14" dy=".35em" text-anchor="start" style="fill-opacity: 1;">SVG</text></g><g class="node" transform="translate(180,158.65383911132812)"><circle r="8" style="fill: rgb(255, 255, 255);"></circle><text x="-14" dy=".35em" text-anchor="end" style="fill-opacity: 1;">安装</text></g><g class="node" transform="translate(360,115.38461303710938)"><circle r="8" style="fill: rgb(255, 255, 255);"></circle><text x="-14" dy=".35em" text-anchor="end" style="fill-opacity: 1;">记事本软件</text></g><g class="node" transform="translate(540,96.15384674072266)"><circle r="8" style="fill: rgb(255, 255, 255);"></circle><text x="14" dy=".35em" text-anchor="start" style="fill-opacity: 1;">Notepad++</text></g><g class="node" transform="translate(540,115.38461303710938)"><circle r="8" style="fill: rgb(255, 255, 255);"></circle><text x="14" dy=".35em" text-anchor="start" style="fill-opacity: 1;">EditPlus</text></g><g class="node" transform="translate(540,134.61538696289062)"><circle r="8" style="fill: rgb(255, 255, 255);"></circle><text x="14" dy=".35em" text-anchor="start" style="fill-opacity: 1;">Sublime Text</text></g><g class="node" transform="translate(360,182.6923065185547)"><circle r="8" style="fill: rgb(255, 255, 255);"></circle><text x="-14" dy=".35em" text-anchor="end" style="fill-opacity: 1;">服务器软件</text></g><g class="node" transform="translate(540,173.07691955566406)"><circle r="8" style="fill: rgb(255, 255, 255);"></circle><text x="14" dy=".35em" text-anchor="start" style="fill-opacity: 1;">Apache Http Server</text></g><g class="node" transform="translate(540,192.3076934814453)"><circle r="8" style="fill: rgb(255, 255, 255);"></circle><text x="14" dy=".35em" text-anchor="start" style="fill-opacity: 1;">Tomcat</text></g><g class="node" transform="translate(360,201.92308044433594)"><circle r="8" style="fill: rgb(255, 255, 255);"></circle><text x="14" dy=".35em" text-anchor="start" style="fill-opacity: 1;">下载D3.js</text></g><g class="node" transform="translate(180,331.73077392578125)"><circle r="8" style="fill: rgb(255, 255, 255);"></circle><text x="-14" dy=".35em" text-anchor="end" style="fill-opacity: 1;">入门</text></g><g class="node" transform="translate(360,240.38461303710938)"><circle r="8" style="fill: rgb(255, 255, 255);"></circle><text x="-14" dy=".35em" text-anchor="end" style="fill-opacity: 1;">选择集</text></g><g class="node" transform="translate(540,230.76922607421875)"><circle r="8" style="fill: rgb(255, 255, 255);"></circle><text x="14" dy=".35em" text-anchor="start" style="fill-opacity: 1;">select</text></g><g class="node" transform="translate(540,250)"><circle r="8" style="fill: rgb(255, 255, 255);"></circle><text x="14" dy=".35em" text-anchor="start" style="fill-opacity: 1;">selectAll</text></g><g class="node" transform="translate(360,298.0769348144531)"><circle r="8" style="fill: rgb(255, 255, 255);"></circle><text x="-14" dy=".35em" text-anchor="end" style="fill-opacity: 1;">绑定数据</text></g><g class="node" transform="translate(540,288.4615478515625)"><circle r="8" style="fill: rgb(255, 255, 255);"></circle><text x="14" dy=".35em" text-anchor="start" style="fill-opacity: 1;">datum</text></g><g class="node" transform="translate(540,307.69232177734375)"><circle r="8" style="fill: rgb(255, 255, 255);"></circle><text x="14" dy=".35em" text-anchor="start" style="fill-opacity: 1;">data</text></g><g class="node" transform="translate(360,331.73077392578125)"><circle r="8" style="fill: rgb(255, 255, 255);"></circle><text x="14" dy=".35em" text-anchor="start" style="fill-opacity: 1;">添加删除元素</text></g><g class="node" transform="translate(360,365.3846130371094)"><circle r="8" style="fill: rgb(255, 255, 255);"></circle><text x="-14" dy=".35em" text-anchor="end" style="fill-opacity: 1;">简单图形</text></g><g class="node" transform="translate(540,346.1538391113281)"><circle r="8" style="fill: rgb(255, 255, 255);"></circle><text x="14" dy=".35em" text-anchor="start" style="fill-opacity: 1;">柱形图</text></g><g class="node" transform="translate(540,365.3846130371094)"><circle r="8" style="fill: rgb(255, 255, 255);"></circle><text x="14" dy=".35em" text-anchor="start" style="fill-opacity: 1;">折线图</text></g><g class="node" transform="translate(540,384.6153869628906)"><circle r="8" style="fill: rgb(255, 255, 255);"></circle><text x="14" dy=".35em" text-anchor="start" style="fill-opacity: 1;">散点图</text></g><g class="node" transform="translate(360,384.6153869628906)"><circle r="8" style="fill: rgb(255, 255, 255);"></circle><text x="14" dy=".35em" text-anchor="start" style="fill-opacity: 1;">比例尺</text></g><g class="node" transform="translate(360,403.8461608886719)"><circle r="8" style="fill: rgb(255, 255, 255);"></circle><text x="14" dy=".35em" text-anchor="start" style="fill-opacity: 1;">生成器</text></g><g class="node" transform="translate(360,423.0769348144531)"><circle r="8" style="fill: rgb(255, 255, 255);"></circle><text x="14" dy=".35em" text-anchor="start" style="fill-opacity: 1;">过渡</text></g><g class="node" transform="translate(180,471.1538391113281)"><circle r="8" style="fill: rgb(255, 255, 255);"></circle><text x="-14" dy=".35em" text-anchor="end" style="fill-opacity: 1;">进阶</text></g><g class="node" transform="translate(360,461.5384521484375)"><circle r="8" style="fill: rgb(255, 255, 255);"></circle><text x="-14" dy=".35em" text-anchor="end" style="fill-opacity: 1;">布局的应用</text></g><g class="node" transform="translate(540,442.30767822265625)"><circle r="8" style="fill: rgb(255, 255, 255);"></circle><text x="14" dy=".35em" text-anchor="start" style="fill-opacity: 1;">饼状图</text></g><g class="node" transform="translate(540,461.5384521484375)"><circle r="8" style="fill: rgb(255, 255, 255);"></circle><text x="14" dy=".35em" text-anchor="start" style="fill-opacity: 1;">树状图</text></g><g class="node" transform="translate(540,480.76922607421875)"><circle r="8" style="fill: rgb(255, 255, 255);"></circle><text x="14" dy=".35em" text-anchor="start" style="fill-opacity: 1;">矩阵树图</text></g><g class="node" transform="translate(360,480.76922607421875)"><circle r="8" style="fill: rgb(255, 255, 255);"></circle><text x="14" dy=".35em" text-anchor="start" style="fill-opacity: 1;">地图</text></g></g></svg>
		
  -->
  
</body></html>